local showprefab = (GetModConfigData("sw_info") == "code")
local Widget = require "widgets/widget"
local Text = require "widgets/text"
local ent_util = require "libs/entutil"
showprefab = showprefab or ent_util:IsHuxi()
local function formatNum(num)
    return GLOBAL.tonumber(string.format("%.2f", num))
end
local function getData(copy)
    local data = {}
    local function ins(text, tex, atlas)
        table.insert(data, {
            text = text,
            atlas = atlas or GLOBAL.GetScrapbookIconAtlas(tex..".tex"),
            image = tex..".tex",
        })
    end
    local function strfood(num)
        num = GLOBAL.tonumber(num)
        if type(num) == "number" then
            if num > 1 then
                return formatNum(num).." 倍腐烂"
            elseif num > 0 then
                return formatNum(1/num).." 倍保鲜"
            elseif num == 0 then
                return "永久保鲜"
            end
            return formatNum(-num).." 倍返鲜"
        else
            return "󰀜"..tostring(num)
        end
    end
    
    local prefab = copy.prefab
    for name, info in pairs(copy.components)do
        if name == "armor" then
            if type(info.maxcondition) == "number" and info.maxcondition>0 then
                ins(info.maxcondition,"icon_health")
            end
            if type(info.absorb_percent) == "number" and info.absorb_percent>0 then
                ins(formatNum(info.absorb_percent*100).."% 护甲", "icon_armor")
            end
        elseif name == "planardefense" then
            if type(info.basedefense) == "number" and info.basedefense>0 then
                ins(formatNum(info.basedefense).." 位防", "icon_shadowaligned")
            end
        elseif name == "waterproofer" then
            if type(info.effectiveness) == "number" and info.effectiveness>0 then
                ins(formatNum(info.effectiveness*100).."%", "icon_wetness")
            end
        elseif name == "fueled" then
            local ft = info.fueltype
            if type(info.maxfuel) == "number" and info.maxfuel>0 then
                if table.contains({GLOBAL.FUELTYPE.USAGE, GLOBAL.FUELTYPE.MAGIC}, ft) then
                    ins(formatNum(info.maxfuel/TUNING.TOTAL_DAY_TIME).." 天", "icon_clothing")
                elseif  table.contains({GLOBAL.FUELTYPE.CAVE, GLOBAL.FUELTYPE.ONEMANBAND, GLOBAL.FUELTYPE.BURNABLE, GLOBAL.FUELTYPE.WORMLIGHT}, ft) then
                    ins(formatNum(info.maxfuel/TUNING.TOTAL_DAY_TIME).." 天", "icon_lightbattery")
                elseif ft == GLOBAL.FUELTYPE.NIGHTMARE then
                    -- 科雷没给接口啊，这里应该弄那个使用的次数
                    if prefab == "armorskeleton" then
                        ins(formatNum(info.maxfuel/TUNING.MED_FUEL).." 次", "icon_needfuel")
                    end
                end
            end
        elseif name == "equippable" then
            if type(info.dapperfn) == "function" then
                local status,result = GLOBAL.pcall(info.dapperfn, nil, GLOBAL.ThePlayer)
                if status and type(result) == "number" and result~=0 then
                    ins(formatNum(result*TUNING.TOTAL_DAY_TIME).."/天", "icon_sanity")
                end
            elseif type(info.dapperness) == "number" and info.dapperness~=0 then
                ins(formatNum(info.dapperness*TUNING.TOTAL_DAY_TIME).."/天", "icon_sanity")
            end
            if type(info.walkspeedmult) == "number" then
                ins(formatNum(info.walkspeedmult*100).."% 速", "icon_fuel"
                -- , GLOBAL.GetInventoryItemAtlas("cane.tex")
            )
            end
        elseif name == "container" then
            if type(info.numslots) == "number" and info.numslots>0 then
                ins(formatNum(info.numslots).." 容量", "icon_needfuel")
            end
        elseif name == "perishable" then
            if type(info.perishtime) == "number" and info.perishtime>0 then
                ins(formatNum(info.perishtime/TUNING.TOTAL_DAY_TIME).." 天", "icon_spoil")
            end
        elseif name == "insulator" then
            if info.type == GLOBAL.SEASONS.WINTER and type(info.insulation)=="number" then
                ins(formatNum(info.insulation).." 保暖", "icon_cold")
            elseif info.type == GLOBAL.SEASONS.SUMMER then
                ins(formatNum(info.insulation).." 隔热", "icon_cold")
            end
        elseif name == "finiteuses" then
            if type(info.total) == "number" and info.total>1 then
                local re, use_mount = false, 1
                if type(info.consumption) == "table" then
                    re, use_mount = GLOBAL.next(info.consumption)
                    if not re or type(use_mount)~="number" then
                        use_mount = 1
                    end
                end
                ins(formatNum(info.total/use_mount).." 耐久", "icon_uses")
            end
        elseif name == "planardamage" then
            if type(info.basedamage) == "number" and info.basedamage>0 then
                ins(formatNum(info.basedamage).." 位伤", "icon_moonaligned")
            end
        elseif name == "weapon" then
            if type(info.damage) == "number" and info.damage>0 then
                ins(formatNum(info.damage).." 伤害", "icon_damage")
            end
            if type(info.attackrange) == "number" then
                ins(formatNum(info.attackrange).." 范围", "icon_stack")
            end
            if info.stimuli == "electric" then
                ins("伤害带电", "icon_fuel")
            end
        elseif name == "shadowlevel" then
            if type(info.level) == "number" then
                ins(info.level.." 暗影", "icon_shadowaligned")
            end
        elseif name == "eater" then
            ins("吃东西", "icon_fuel")
        elseif name == "tool" and info.tough then
            ins("强力工具", "icon_fuel")
        elseif name == "explosive" then
            if type(info.explosivedamage) == "number" and info.explosivedamage>0 then
                ins(formatNum(info.explosivedamage).." 爆炸", "icon_damage")
            end
        elseif name == "healer" then
            if type(info.health) == "number" and info.health>0 then
                ins(formatNum(info.health).." 生命", "icon_health")
            end
        elseif name == "bundlemaker" then
            ins("永久保鲜", "icon_food")
        elseif name == "edible" then
            local ft = info.foodtype
            if not table.contains({GLOBAL.FOODTYPE.WOOD, GLOBAL.FOODTYPE.ELEMENTAL, GLOBAL.FOODTYPE.ROUGHAGE,}, ft)then
                if type(info.healthvalue) == "number" then
                    ins(formatNum(info.healthvalue).." 生命", "icon_health")
                end
                if type(info.sanityvalue) == "number" then
                    ins(formatNum(info.sanityvalue).." 理智", "icon_sanity")
                end
                if type(info.hungervalue) == "number" then
                    ins(formatNum(info.hungervalue).." 饱食", "icon_hunger")
                end
            end
        elseif name == "upgrademodule" then
            if type(info.slots) == "number" then
                ins(formatNum(info.slots).." 插槽", "icon_needfuel")
            end
            if prefab == "wx78module_maxhealth" then
                ins("+50上限", "icon_health")
            elseif prefab == "wx78module_movespeed" then
                ins("+25% 速", "icon_fuel")
            elseif prefab == "wx78module_movespeed2" then
                ins("+25% 速", "icon_fuel")
            elseif prefab == "wx78module_maxhunger1" then
                ins("+40上限", "icon_hunger")
            elseif prefab == "wx78module_maxhunger2" then
                ins("+100上限", "icon_hunger")
                ins("-20%消耗", "icon_hunger")
            elseif prefab == "wx78module_maxsanity1" then
                ins("+40上限", "icon_sanity")
            elseif prefab == "wx78module_maxsanity" then
                ins("+100上限", "icon_sanity")
                ins("+16/天", "icon_sanity")
            elseif prefab == "wx78module_maxhealth2" then
                ins("+150上限", "icon_health")
            elseif prefab == "wx78module_cold" then
                ins("-20 体温", "icon_cold")
                ins(strfood(.75), "icon_food")
            elseif prefab == "wx78module_heat" then
                ins("+20 体温", "icon_heat")
                ins(strfood(1.25), "icon_food")
            elseif prefab == "wx78module_light" then
                ins("发光！", "icon_lightbattery")
            elseif prefab == "wx78module_nightvision" then
                ins("夜视！", "icon_lightbattery")
            elseif prefab == "wx78module_music" then
                ins("音乐！", "icon_sanity")
                ins(formatNum(TUNING.WX78_MUSIC_SANITYAURA*TUNING.TOTAL_DAY_TIME).."/天", "icon_sanity")
            elseif prefab == "wx78module_taser" then
                ins("带电反伤", "icon_damage")
            elseif prefab == "wx78module_bee" then
                ins("+100上限", "icon_sanity")
                ins("+80/天", "icon_health")
            end
        end
    end
    if prefab == "armor_bramble" then
        ins(formatNum(TUNING.ARMORBRAMBLE_DMG).." 反伤", "icon_damage")
    elseif prefab == "bomb_lunarplant" then
        ins(formatNum(TUNING.BOMB_LUNARPLANT_PLANAR_DAMAGE).." 延伤", "icon_moonaligned")
    elseif prefab == "batbat" then
        ins(formatNum(TUNING.BATBAT_DRAIN).." 吸血", "icon_health")
    elseif prefab == "seedpouch" then
        ins(strfood(TUNING.SEEDPOUCH_PRESERVER_RATE), "icon_food")
    elseif prefab == "fish_box" then
        ins("对鱼返鲜", "icon_food")
    elseif prefab == "magician_chest" then
        ins("12 容量", "icon_needfuel")
        ins(strfood(1.5), "icon_food")
    end
    if table.contains(copy.tags, "fridge") then
        ins(strfood(TUNING.PERISH_FRIDGE_MULT), "icon_food")
    elseif table.contains(copy.tags, "foodpreserver") then
        ins(strfood(TUNING.PERISH_FOOD_PRESERVER_MULT), "icon_food")
    elseif table.contains(copy.tags, "cage") then
        ins(strfood(TUNING.PERISH_CAGE_MULT), "icon_food")
    elseif table.contains(copy.tags, "spoiler") then
        ins(strfood(TUNING.PERISH_GROUND_MULT), "icon_food")
    elseif table.contains(copy.tags, "saltbox") then
        ins(strfood(TUNING.PERISH_SALTBOX_MULT), "icon_food")
    elseif table.contains(copy.tags, "portablestorage") then
        ins(strfood(TUNING.BEARGERFUR_SACK_PRESERVER_RATE), "icon_food")
    elseif table.contains(copy.tags, "dumbbell") then
        ins("锻炼身体", "icon_fuel")
    end



    return data
end

local Image = require "widgets/image"
local imgsize = 48
AddClassPostConstruct("widgets/redux/craftingmenu_details", function (self)
    local _PopulateRecipeDetailPanel = self.PopulateRecipeDetailPanel    
    self.PopulateRecipeDetailPanel = function(self, data, skin_name, ...)        
        local re = _PopulateRecipeDetailPanel(self, data, skin_name, ...)
        if self.crafting_hud and self.crafting_hud:IsCraftingOpen() then
            local prefab = data and data.recipe and data.recipe.name
            if type(prefab) == "string" and self.panel_width then
                if string.sub(prefab, 1, 10) == "transmute_" then
                    prefab = string.sub(prefab, 11)
                end
                -- 不确定是否有效
                if self.i_p then
                    self.i_p:Kill()
                end
                self.i_p = self:AddChild(Widget("info_panel"))
                self.i_p:SetPosition(-self.panel_width / 4, -120)
                local width = self.panel_width/2
                local datas = getData(ent_util:ClonePrefab(prefab))
                for i, data in ipairs(datas)do
                    local w = self.i_p:AddChild(Widget("info_conn"))
                    local img = w:AddChild(Image(data.atlas, data.image))
                    img:ScaleToSize(imgsize, imgsize)
                    local text = w:AddChild(Text(GLOBAL.HEADERFONT, 22, data.text, GLOBAL.UICOLOURS.WHITE))
                    w:SetPosition(i%2==0 and width/14 or width/14-width/2, -math.floor((i-1)/2)*50)
                    text:SetPosition(imgsize + text:GetRegionSize()/4, 0)
                end 
                if prefab and showprefab then
                    local w = self.i_p:AddChild(Widget("info_conn"))
                    local img = w:AddChild(Image(GLOBAL.GetScrapbookIconAtlas("icon_stack.tex"), "icon_stack.tex"))
                    img:ScaleToSize(imgsize, imgsize)
                    local text = w:AddChild(Text(GLOBAL.HEADERFONT, 22, prefab, GLOBAL.UICOLOURS.WHITE))
                    w:SetPosition(width/14-width/2, -math.floor((#datas+1)/2)*50)
                    text:SetPosition(imgsize + text:GetRegionSize()/2, 0)
                end
                -- self.i_p.OnMouseButton = function(_, button, down)
                --     if button == 1000 and down and GLOBAL.TheInput:IsControlPressed(GLOBAL.CONTROL_FORCE_INSPECT) and GLOBAL.ThePlayer.HUD._StatusAnnouncer then
                --         -- 没必要加快捷宣告吧
                --     end
                -- end
            end
        end
        return re
    end
end)



-- 图鉴显示代码
AddClassPostConstruct("screens/redux/scrapbookscreen", function(self)
    local _PopulateInfoPanel = self.PopulateInfoPanel
    self.PopulateInfoPanel = function(self, data, ...)
        local re = _PopulateInfoPanel(self, data, ...)
        local c = self and self.scroll_area and self.scroll_area.context and self.scroll_area.context.widget and self.scroll_area.context.widget.children
        if type(c)=="table" then
            for k in pairs(c)do
                if type(k) == "table" and type(k.string) == "string" and (string.sub(k.string, -1) ~= "/") then
                    local prefab = data.name
                    if prefab then
                        local code = k:AddChild(Text(GLOBAL.HEADERFONT, 25, prefab, GLOBAL.UICOLOURS.GOLD))
                        code:SetHAlign(GLOBAL.ANCHOR_LEFT)
                        code:SetPosition(200, 0)
                    end
                    break
                end
            end
        end
        return re
    end
end)

local debugger = GetModConfigData("sw_debugger")
local function isAssignmentError(title, text)
    local errstrs = {"SpawnPrefab", "mainfunctions", "ClonePrefab", "PopulateRecipeDetailPanel"}
    if type(title) == "string" and type(text) == "string" then
        for _, fstr in pairs(errstrs)do
            if not string.find(text, fstr) then
                return false
            end
        end
        return text:match("/mods/(workshop.-)/")
    end
end

-- 处理报错
AddClassPostConstruct("widgets/scripterrorwidget", function(self, title, text, buttons, texthalign, additionaltext, ...)
    if debugger then
        local e_mod = isAssignmentError(title, text)
        if e_mod then
            if self.title then
                self.title:SetString("蘑菇慕斯 · 智能模组󰀜")
            end
            if self.text then
                local mod = GLOBAL.KnownModIndex:GetModInfo(e_mod)
                local name = mod and mod.name
                local version = mod and mod.version
                if name and version then
                    self.text:SetString("这个错误是由于模组【"..name..version.."】的代码不规范引起的！\n但你可以通过修改【蘑菇慕斯】的设置来解决报错，请关闭慕斯的设置【信息组件】来修复此问题！\n\n\n"..text)
                    if self.additionaltext then
                        self.additionaltext:SetString("请关闭【蘑菇慕斯 · 朝花夕拾󰀜】的【信息组件】功能！\n 模组崩溃反馈QQ群：603484152")
                    end
                end
            end
        end
    end
end)